#ifndef GAMEKIT_NULLABLE_H
#define GAMEKIT_NULLABLE_H

#include "gamekit.h"

template<typename T>
class GK_API Nullable
{
private:
	bool m_hasValue;
	T m_t;

public:
	Nullable(void);
	Nullable(const T& t);
	Nullable(const Nullable<T>& t);

	operator T();
	Nullable<T> operator =(const T& t);
	Nullable<T> operator =(const Nullable<T>& t);

	bool HasValue(void) const;
	T Value(void) const;
	void Clear(void);
};

template<typename T>
Nullable<T>::Nullable(void) 
	: m_hasValue(false)
{
}

template<typename T>
Nullable<T>::Nullable(const T& t)
	: m_t(t), m_hasValue(false)
{
}

template<typename T>
Nullable<T>::Nullable(const Nullable<T>& t)
	: m_t(t.m_t), m_hasValue(t.m_hasValue)
{
}

template<typename T>
Nullable<T>::operator T()
{
	if(!m_hasValue)
	{
		throw std::exception("Has no value set");
	}

	return m_t;
}

template<typename T>
Nullable<T> Nullable<T>::operator =(const T& t)
{
	m_t = t;
	m_hasValue = true;

	return *this;
}

template<typename T>
Nullable<T> Nullable<T>::operator =(const Nullable<T>& t)
{
	m_t = t.m_t;
	m_hasValue = t.m_hasValue;

	return *this;
}

template<typename T>
bool Nullable<T>::HasValue() const
{
	return m_hasValue;
}

template<typename T>
T Nullable<T>::Value() const
{
	if(!m_hasValue)
	{
		throw std::exception("Has no value set");
	}

	return m_t;
}

template<typename T>
void Nullable<T>::Clear()
{
	m_hasValue = false;
}

#endif
